<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="keywords" content="imlgw,半岛铁盒,blog,Java博客,程序员,个人博客,java開發,程序員,個人博客,Java">
    <meta name="description" content="大悲无泪，大悟无言，大笑无声。">
    <meta name="author" content="Resolmi">
    
    <title>
        
            ThreadPoolExecutor源码解析 |
        
        Tadow
    </title>
    
<link rel="stylesheet" href="/css/style.css">

    <link rel="shortcut icon" href="https://static.imlgw.top/blog/20210731/BtJz541CcmJU.ico">
    <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/css/font-awesome.min.css">
    <script id="hexo-configurations">
    let KEEP = window.KEEP || {};
    KEEP.hexo_config = {"hostname":"imlgw.top","root":"/","language":"zh-CN","path":"search.json"};
    KEEP.theme_config = {"toc":{"enable":true,"number":true,"expand_all":true,"init_open":true},"style":{"primary_color":"#0066CC","avatar":"https://static.imlgw.top/blog/20210731/3C7hCSRR3lfq.png","favicon":"https://static.imlgw.top/blog/20210731/BtJz541CcmJU.ico","article_img_align":"left","left_side_width":"260px","content_max_width":"920px","hover":{"shadow":false,"scale":true},"first_screen":{"enable":true,"background_img":"/images/image.svg","description":"Keep It Simple & Stupid."},"scroll":{"progress_bar":{"enable":true},"percent":{"enable":true}}},"local_search":{"enable":true,"preload":false},"code_copy":{"enable":true,"style":"default"},"pjax":{"enable":true},"lazyload":{"enable":true},"version":"3.4.3"};
    KEEP.language_ago = {"second":"%s 秒前","minute":"%s 分钟前","hour":"%s 小时前","day":"%s 天前","week":"%s 周前","month":"%s 月前","year":"%s 年前"};
  </script>
<meta name="generator" content="Hexo 5.4.0"><link rel="stylesheet" href="/css/prism.css" type="text/css"></head>


<body>
<div class="progress-bar-container">
    
        <span class="scroll-progress-bar"></span>
    

    
        <span class="pjax-progress-bar"></span>
        <span class="pjax-progress-icon">
            <i class="fas fa-circle-notch fa-spin"></i>
        </span>
    
</div>


<main class="page-container">

    

    <div class="page-main-content">

        <div class="page-main-content-top">
            <header class="header-wrapper">

    <div class="header-content">
        <div class="left">
            
            <a class="logo-title" href="/">
                Tadow
            </a>
        </div>

        <div class="right">
            <div class="pc">
                <ul class="menu-list">
                    
                        <li class="menu-item">
                            <a class=""
                               href="/"
                            >
                                首页
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/archives"
                            >
                                归档
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/categories"
                            >
                                分类
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/sbe"
                            >
                                订阅
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/links"
                            >
                                友链
                            </a>
                        </li>
                    
                        <li class="menu-item">
                            <a class=""
                               href="/about"
                            >
                                关于
                            </a>
                        </li>
                    
                    
                        <li class="menu-item search search-popup-trigger">
                            <i class="fas fa-search"></i>
                        </li>
                    
                </ul>
            </div>
            <div class="mobile">
                
                    <div class="icon-item search search-popup-trigger"><i class="fas fa-search"></i></div>
                
                <div class="icon-item menu-bar">
                    <div class="menu-bar-middle"></div>
                </div>
            </div>
        </div>
    </div>

    <div class="header-drawer">
        <ul class="drawer-menu-list">
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/">首页</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/archives">归档</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/categories">分类</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/sbe">订阅</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/links">友链</a>
                </li>
            
                <li class="drawer-menu-item flex-center">
                    <a class=""
                       href="/about">关于</a>
                </li>
            
        </ul>
    </div>

    <div class="window-mask"></div>

</header>


        </div>

        <div class="page-main-content-middle">

            <div class="main-content">

                
                    <div class="fade-in-down-animation">
    <div class="article-content-container">

        <div class="article-title">
            <span class="title-hover-animation">ThreadPoolExecutor源码解析</span>
        </div>

        
            <div class="article-header">
                <div class="avatar">
                    <img src="https://static.imlgw.top/blog/20210731/3C7hCSRR3lfq.png">
                </div>
                <div class="info">
                    <div class="author">
                        <span class="name">Resolmi</span>
                        
                            <span class="author-label">BOSS</span>
                        
                    </div>
                    <div class="meta-info">
                        <div class="article-meta-info">
    <span class="article-date article-meta-item">
        <i class="fas fa-edit"></i>&nbsp;2019-07-30 00:00:00
    </span>
    
        <span class="article-categories article-meta-item">
            <i class="fas fa-folder"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/categories/%E5%B9%B6%E5%8F%91/">并发</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    
    
        <span class="article-tags article-meta-item">
            <i class="fas fa-tags"></i>&nbsp;
            <ul>
                
                    <li>
                        <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/">多线程</a>&nbsp;
                    </li>
                
                    <li>
                        | <a href="/tags/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/">并发编程</a>&nbsp;
                    </li>
                
            </ul>
        </span>
    

    
    
        <span class="article-wordcount article-meta-item">
            <i class="fas fa-file-word"></i>&nbsp;<span>7.1k 字</span>
        </span>
    
    
        <span class="article-min2read article-meta-item">
            <i class="fas fa-clock"></i>&nbsp;<span>29 分钟</span>
        </span>
    
    
        <span class="article-pv article-meta-item">
            <i class="fas fa-eye"></i>&nbsp;<span id="busuanzi_value_page_pv"></span>
        </span>
    
</div>

                    </div>
                </div>
            </div>
        

        <div class="article-content markdown-body">
            <h2 id="深入ThreadPoolExecutor源码"><a href="#深入ThreadPoolExecutor源码" class="headerlink" title="深入ThreadPoolExecutor源码"></a>深入ThreadPoolExecutor源码</h2><h3 id="类结构"><a href="#类结构" class="headerlink" title="类结构"></a>类结构</h3><p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top/blog/20190802/wTkHh1NbyM8K.png?imageslim"
                      alt="mark"
                ></p>
<p>这里主要要说的是 <code>ThreadPoolExecutor</code>类</p>
<h3 id="线程池状态"><a href="#线程池状态" class="headerlink" title="线程池状态"></a>线程池状态</h3><p>打开源码映入眼帘的就是这几个字段和方法，对应的就是线程池的一些运行状态和相关方法</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//控制线程池中数量和状态的字段,用AtomicInteger保存</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> AtomicInteger ctl = <span class="keyword">new</span> AtomicInteger(ctlOf(RUNNING, <span class="number">0</span>));</span><br><span class="line"><span class="comment">//count bit顾名思义就是 workerCount的位数，这里是29</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> COUNT_BITS = Integer.SIZE - <span class="number">3</span>;</span><br><span class="line"><span class="comment">//1&lt;&lt;29 -1 == 1111....1111(29个1) 线程数(workerCount)上限 大约5亿</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> CAPACITY   = (<span class="number">1</span> &lt;&lt; COUNT_BITS) - <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// runState is stored in the high-order bits</span></span><br><span class="line"><span class="comment">//高三位存放状态，相应的低29位就是workerCount</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> RUNNING    = -<span class="number">1</span> &lt;&lt; COUNT_BITS;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> SHUTDOWN   =  <span class="number">0</span> &lt;&lt; COUNT_BITS;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> STOP       =  <span class="number">1</span> &lt;&lt; COUNT_BITS;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TIDYING    =  <span class="number">2</span> &lt;&lt; COUNT_BITS;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TERMINATED =  <span class="number">3</span> &lt;&lt; COUNT_BITS;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Packing and unpacking ctl</span></span><br><span class="line"><span class="comment">// 拆解ctl获取状态和数量</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">runStateOf</span><span class="params">(<span class="keyword">int</span> c)</span>     </span>&#123; <span class="keyword">return</span> c &amp; ~CAPACITY; &#125;</span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">workerCountOf</span><span class="params">(<span class="keyword">int</span> c)</span>  </span>&#123; <span class="keyword">return</span> c &amp; CAPACITY; &#125;</span><br><span class="line"><span class="comment">// 拼接状态和数量得到ctl</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">ctlOf</span><span class="params">(<span class="keyword">int</span> rs, <span class="keyword">int</span> wc)</span> </span>&#123; <span class="keyword">return</span> rs | wc; &#125;</span><br></pre></td></tr></table></figure>

<h4 id="状态转换过程"><a href="#状态转换过程" class="headerlink" title="状态转换过程"></a>状态转换过程</h4><p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top/blog/20190802/EWlphYbCMVjv.png?imageslim"
                      alt="mark"
                ></p>
<p>💡 <strong>RUNNING</strong> ：能接受新提交的任务，并且也能处理阻塞队列中的任务；</p>
<p>💡 <strong>SHUTDOWN</strong>：关闭状态，不再接受新提交的任务，但却可以继续处理阻塞队列中已保存的任务。在线程池处于 <code>RUNNING</code> 状态时，调用 <code>shutdown()</code>方法会使线程池进入到该状态。（<code>finalize()</code> 方法在执行过程中也会调用shutdown()方法进入该状态）</p>
<p>💡 <strong>STOP</strong>：不能接受新任务，也不处理队列中的任务，会中断正在处理任务的线程。在线程池处于 <code>RUNNING</code> 或 <code>SHUTDOWN</code> 状态时，调用 <code>shutdownNow()</code> 方法会使线程池进入到该状态</p>
<p>💡 <strong>TIDYING</strong>：如果所有的任务都已终止了，workerCount (有效线程数) 为0，线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态</p>
<p>💡 <strong>TERMINATED</strong>：在terminated() 方法执行完后进入该状态，默认terminated()方法中什么也没有做。</p>
<p>进入<code>TERMINATED</code>的条件如下：</p>
<ul>
<li>线程池不是RUNNING状态；</li>
<li>线程池状态不是TIDYING状态或TERMINATED状态；</li>
<li>如果线程池状态是SHUTDOWN并且workerQueue为空；</li>
<li>workerCount为0；</li>
<li>设置TIDYING状态成功。</li>
</ul>
<h3 id="成员变量"><a href="#成员变量" class="headerlink" title="成员变量"></a>成员变量</h3><p>再往下，就会看见一些很重要的成员变量</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//任务缓存队列，存放待执行的任务</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> BlockingQueue&lt;Runnable&gt; workQueue; </span><br><span class="line"><span class="comment">//可重入锁，线程池主要的锁</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">new</span> ReentrantLock();</span><br><span class="line"><span class="comment">//线程集合(线程池的workers集合)</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> HashSet&lt;Worker&gt; workers = <span class="keyword">new</span> HashSet&lt;Worker&gt;();</span><br><span class="line"><span class="comment">//对应的条件变量</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> Condition termination = mainLock.newCondition(); </span><br><span class="line"><span class="comment">//用来记录线程池中曾经出现过的最大线程数，和线程池容量没有关系</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">int</span> largestPoolSize;</span><br><span class="line"><span class="comment">//用来记录已经执行完毕的任务个数</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">long</span> completedTaskCount; </span><br><span class="line"><span class="comment">//工厂方法，用来创建线程</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> ThreadFactory threadFactory; </span><br><span class="line"><span class="comment">//拒绝策略</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> RejectedExecutionHandler handler; </span><br><span class="line"><span class="comment">//线程闲置时候的最大存活时间</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">long</span> keepAliveTime; </span><br><span class="line"><span class="comment">//是否允许核心线程闲置的时候超时</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">boolean</span> allowCoreThreadTimeOut; </span><br><span class="line"><span class="comment">//核心线程数</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">int</span> corePoolSize; </span><br><span class="line"><span class="comment">//最大线程数</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">int</span> maximumPoolSize; </span><br><span class="line"><span class="comment">//默认的拒绝策略：AbortPolicy直接拒绝并抛异常</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> RejectedExecutionHandler defaultHandler = <span class="keyword">new</span> AbortPolicy();</span><br></pre></td></tr></table></figure>

<h3 id="execute"><a href="#execute" class="headerlink" title="execute()"></a>execute()</h3><p> <strong>源码分析</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">execute</span><span class="params">(Runnable command)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (command == <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//获取线程池的状态和线程数量</span></span><br><span class="line">    <span class="keyword">int</span> c = ctl.get();</span><br><span class="line">    <span class="keyword">if</span> (workerCountOf(c) &lt; corePoolSize) &#123; <span class="comment">//workerCount小于核心线程数量</span></span><br><span class="line">        <span class="comment">//将任务添加到workers中，第二个参数代表是否根据corePoolSize来添加线程，false则根据maxPoolSize</span></span><br><span class="line">        <span class="keyword">if</span> (addWorker(command, <span class="keyword">true</span>))</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        <span class="comment">//添加失败，重新获取ctl</span></span><br><span class="line">        c = ctl.get();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//上面添加到workers中失败，有可能是核心线程不够用了或者线程池不是运行状态</span></span><br><span class="line">    <span class="comment">//如果线程池是Running状态 尝试添加任务到阻塞队列中</span></span><br><span class="line">    <span class="keyword">if</span> (isRunning(c) &amp;&amp; workQueue.offer(command)) &#123;</span><br><span class="line">        <span class="comment">//添加到等待队列成功，重新获取ctl</span></span><br><span class="line">        <span class="keyword">int</span> recheck = ctl.get();</span><br><span class="line">        <span class="comment">//如果线程池不是Running状态就从等待队列中remove这个任务</span></span><br><span class="line">        <span class="keyword">if</span> (! isRunning(recheck) &amp;&amp; remove(command))</span><br><span class="line">            reject(command); <span class="comment">//采用拒绝策略拒绝该任务</span></span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (workerCountOf(recheck) == <span class="number">0</span>)</span><br><span class="line">            <span class="comment">//线程池Running但是没有线程</span></span><br><span class="line">            <span class="comment">//创建一个线程但是不传入Runnable(已经在阻塞队列中了)</span></span><br><span class="line">            addWorker(<span class="keyword">null</span>, <span class="keyword">false</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//两种情况</span></span><br><span class="line">    <span class="comment">//1. 线程池不是Running状态并且command不为null，addWorker会直接false然后拒绝这个任务</span></span><br><span class="line">    <span class="comment">//2. 添加到workQueue(阻塞队列)失败，也就是 queue满了，可能是需要扩容了</span></span><br><span class="line">    <span class="comment">//   所以后面的参数是false，添加失败也会直接拒绝</span></span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (!addWorker(command, <span class="keyword">false</span>))</span><br><span class="line">        reject(command);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里要理解addWorker的第二个参数，true则代表当前线程池的<strong>上界</strong>仍然是corePoolSize，后面的addWorker会根据上界来判断是否增加线程，false则代表<strong>上界</strong>是maximumPoolSize，这一点在后面的分析中会看到。</p>
<p><strong>Executor大致执行流程</strong></p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top/blog/20190803/j3xQrmOkc3Kl.png?imageslim"
                      alt="mark"
                ></p>
<h3 id="addWorker"><a href="#addWorker" class="headerlink" title="addWorker()"></a>addWorker()</h3><p><code>addWorker()</code> 的作用就是创建线程(Worker)并且添加到Workers集合中，然后启动线程</p>
<p><strong>源码分析</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">boolean</span> <span class="title">addWorker</span><span class="params">(Runnable firstTask, <span class="keyword">boolean</span> core)</span> </span>&#123;</span><br><span class="line">    retry:</span><br><span class="line">    <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">        <span class="keyword">int</span> c = ctl.get();</span><br><span class="line">        <span class="keyword">int</span> rs = runStateOf(c);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// rs&gt;=SHUTDOWN说明不是RUNNING状态</span></span><br><span class="line">        <span class="keyword">if</span> (rs &gt;= SHUTDOWN &amp;&amp; !(rs == SHUTDOWN &amp;&amp; firstTask == <span class="keyword">null</span> &amp;&amp;!workQueue.isEmpty()))</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">            <span class="keyword">int</span> wc = workerCountOf(c);</span><br><span class="line">            <span class="comment">//如果大于可允许的最大线程数，或者大于当前的线程池的上界，直接false</span></span><br><span class="line">            <span class="comment">//上面传入的第二个参数的作用体现出来了，为true上界则是corePoolSize</span></span><br><span class="line">            <span class="keyword">if</span> (wc &gt;= CAPACITY || wc &gt;= (core ? corePoolSize : maximumPoolSize))</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="comment">//利用CAS自增 增大workCount线程数，成功后就跳出循环</span></span><br><span class="line">            <span class="keyword">if</span> (compareAndIncrementWorkerCount(c))</span><br><span class="line">                <span class="keyword">break</span> retry;</span><br><span class="line">            <span class="comment">//CAS失败，重新获取ctl</span></span><br><span class="line">            c = ctl.get();  <span class="comment">// Re-read ctl</span></span><br><span class="line">            <span class="comment">//判断还是不是Running状态(能到这里说明rs==Running状态)，不是的话就跳出去重新来过</span></span><br><span class="line">            <span class="keyword">if</span> (runStateOf(c) != rs)</span><br><span class="line">                <span class="keyword">continue</span> retry;</span><br><span class="line">            <span class="comment">// else CAS failed due to workerCount change; retry inner loop</span></span><br><span class="line">            <span class="comment">// CAS失败并且还是Running状态，继续自旋尝试自增</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//线程是否启动，以及线程是否添加</span></span><br><span class="line">    <span class="keyword">boolean</span> workerStarted = <span class="keyword">false</span>;</span><br><span class="line">    <span class="keyword">boolean</span> workerAdded = <span class="keyword">false</span>;</span><br><span class="line">    Worker w = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">//创建一个Worker(对线程的封装)</span></span><br><span class="line">        w = <span class="keyword">new</span> Worker(firstTask);</span><br><span class="line">        <span class="keyword">final</span> Thread t = w.thread;</span><br><span class="line">        <span class="keyword">if</span> (t != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">            mainLock.lock();</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">// Recheck while holding lock.</span></span><br><span class="line">                <span class="comment">// Back out on ThreadFactory failure or if</span></span><br><span class="line">                <span class="comment">// shut down before lock acquired.</span></span><br><span class="line">                <span class="keyword">int</span> rs = runStateOf(ctl.get());</span><br><span class="line">				<span class="comment">//是RUNNING状态 或者 是SHUTDOWN状态且没有提交任务(SHUTDOWN状态还可以执行阻塞队列的任务)</span></span><br><span class="line">                <span class="keyword">if</span> (rs &lt; SHUTDOWN ||</span><br><span class="line">                    (rs == SHUTDOWN &amp;&amp; firstTask == <span class="keyword">null</span>)) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (t.isAlive()) <span class="comment">// precheck that t is startable</span></span><br><span class="line">                        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalThreadStateException();</span><br><span class="line">                    <span class="comment">//添加到工作集中</span></span><br><span class="line">                    workers.add(w);</span><br><span class="line">                    <span class="keyword">int</span> s = workers.size();</span><br><span class="line">                    <span class="keyword">if</span> (s &gt; largestPoolSize)</span><br><span class="line">                        largestPoolSize = s; <span class="comment">//记录最大值</span></span><br><span class="line">                    workerAdded = <span class="keyword">true</span>; <span class="comment">//添加成功</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                mainLock.unlock();</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (workerAdded) &#123;</span><br><span class="line">                <span class="comment">//启动线程，执行Worker的run方法</span></span><br><span class="line">                t.start(); </span><br><span class="line">                workerStarted = <span class="keyword">true</span>; <span class="comment">//启动成功</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (! workerStarted)</span><br><span class="line">            <span class="comment">//启动失败，回滚workers并尝试关闭线程池</span></span><br><span class="line">            addWorkerFailed(w);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> workerStarted;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>🔸 首先判断当前线程池的状态是否适合继续addWorker，分析这里的if条件，RUNNING不会false ，STOP，TIDYING，TERMINATED直接false，SHUTDOWN状态如果firstTask为空 阻塞队列中还有任务的时候不会false，其他情况都false。</p>
<p>🔸 获取当前的workerCount判断是否超过了当前的上界，这里就用到了第二个参数</p>
<p>🔸 然后利用CAS自旋增加workerCount</p>
<p>🔸 创建Worker对象，获取mainLock并加锁，因为workers是HashSet并不是线程安全的</p>
<p>🔸 再次获取线程池转台并判断是否合法，合法就添加到workers中，然后在finally块中释放锁</p>
<p>🔸 根据前面的workerAdded 判断是否启动线程</p>
<p>🔸 在最终的finally块中根据是否启动成功来决定是否回滚</p>
<h3 id="addWorkerFailed"><a href="#addWorkerFailed" class="headerlink" title="addWorkerFailed()"></a>addWorkerFailed()</h3><p>启动失败，回滚之前的添加操作</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">addWorkerFailed</span><span class="params">(Worker w)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">    <span class="comment">//获取锁</span></span><br><span class="line">    mainLock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (w != <span class="keyword">null</span>)</span><br><span class="line">            <span class="comment">//从workers中移除</span></span><br><span class="line">            workers.remove(w);</span><br><span class="line">        <span class="comment">//减少workerCount</span></span><br><span class="line">        decrementWorkerCount();</span><br><span class="line">        <span class="comment">//尝试关闭线程池</span></span><br><span class="line">        tryTerminate();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        mainLock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Worker类"><a href="#Worker类" class="headerlink" title="Worker类"></a>Worker类</h3><p>封装了线程对象，线程池维护的就是这些worker</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> <span class="class"><span class="keyword">class</span> <span class="title">Worker</span> <span class="keyword">extends</span> <span class="title">AbstractQueuedSynchronizer</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * This class will never be serialized, but we provide a</span></span><br><span class="line"><span class="comment">     * serialVersionUID to suppress a javac warning.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID = <span class="number">6138294804551838833L</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Thread this worker is running in.  Null if factory fails. */</span></span><br><span class="line">    <span class="keyword">final</span> Thread thread;</span><br><span class="line">    <span class="comment">/** Initial task to run.  Possibly null. */</span></span><br><span class="line">    Runnable firstTask; <span class="comment">//传入的任务</span></span><br><span class="line">    <span class="comment">/** Per-thread task counter */</span></span><br><span class="line">    <span class="keyword">volatile</span> <span class="keyword">long</span> completedTasks;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Creates with given first task and thread from ThreadFactory.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> firstTask the first task (null if none)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Worker(Runnable firstTask) &#123;</span><br><span class="line">        setState(-<span class="number">1</span>); <span class="comment">// 设置状态为 -1</span></span><br><span class="line">        <span class="keyword">this</span>.firstTask = firstTask;</span><br><span class="line">        <span class="comment">//根据工厂方法创建线程</span></span><br><span class="line">        <span class="comment">//将Worker传递进去，作为Thread的参数</span></span><br><span class="line">        <span class="comment">//new Thread(Worker worker);</span></span><br><span class="line">        <span class="keyword">this</span>.thread = getThreadFactory().newThread(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Delegates main run loop to outer runWorker  */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        runWorker(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Lock methods</span></span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">    <span class="comment">// The value 0 represents the unlocked state.</span></span><br><span class="line">    <span class="comment">// The value 1 represents the locked state.</span></span><br><span class="line">    <span class="comment">// 是否获取到了锁</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">boolean</span> <span class="title">isHeldExclusively</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> getState() != <span class="number">0</span>; </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">boolean</span> <span class="title">tryAcquire</span><span class="params">(<span class="keyword">int</span> unused)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//利用CAS设置state</span></span><br><span class="line">        <span class="comment">//很明显这里是个不可重入的独占锁，具体可以对比ReentrantLock的实现方法</span></span><br><span class="line">        <span class="keyword">if</span> (compareAndSetState(<span class="number">0</span>, <span class="number">1</span>)) &#123;</span><br><span class="line">            <span class="comment">//继承自AbstractOwnableSynchronizer</span></span><br><span class="line">            <span class="comment">//保存当前的持有锁的线程</span></span><br><span class="line">            setExclusiveOwnerThread(Thread.currentThread());</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//释放锁设置state=0</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">boolean</span> <span class="title">tryRelease</span><span class="params">(<span class="keyword">int</span> unused)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//设置独占锁线程为空</span></span><br><span class="line">        setExclusiveOwnerThread(<span class="keyword">null</span>);</span><br><span class="line">        setState(<span class="number">0</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">lock</span><span class="params">()</span>        </span>&#123; acquire(<span class="number">1</span>); &#125; <span class="comment">//最终会调用tryAcquire(1);</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">tryLock</span><span class="params">()</span>  </span>&#123; <span class="keyword">return</span> tryAcquire(<span class="number">1</span>); &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">unlock</span><span class="params">()</span>      </span>&#123; release(<span class="number">1</span>); &#125; <span class="comment">//最终会调用tryRelease(1);</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">isLocked</span><span class="params">()</span> </span>&#123; <span class="keyword">return</span> isHeldExclusively(); &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//打断已经启动的线程</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">interruptIfStarted</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Thread t;</span><br><span class="line">        <span class="keyword">if</span> (getState() &gt;= <span class="number">0</span> &amp;&amp; (t = thread) != <span class="keyword">null</span> &amp;&amp; !t.isInterrupted()) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                t.interrupt();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (SecurityException ignore) &#123;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里可以看到Worker继承了AQS并且实现了Runnable接口，然后借助AQS实现了一个<code>独占的不可重入的锁</code>，其实这也是很巧妙的一点（这里我和博客上的理解有点出入）。</p>
<p>到这里大家肯定会有疑问，为什么这里要实现AQS然后实现一个锁？既然要又为什么要实现一个不可重入的，而不直接使用<code>ReentrantLock</code> 那不是更加方便么？？除此之外还有一个小细节就是构造器里面为什么<code>setState(-1)</code>  这样不就获取不到锁了么？？</p>
<p>其实这是为了后面<code>shutdown</code>的时候<code>interruptIdleWorkers</code>能判断出线程是否在工作，从而打断那些空闲的线程。如果使用可重入锁的话就无法通过<code>tryLock()</code> 来判断线程是否在工作。而<code>setState(-1)</code> 则是为了防止在任务没有开始前被打断</p>
<h3 id="runWorker"><a href="#runWorker" class="headerlink" title="runWorker()"></a>runWorker()</h3><p>在上面<code>AddWorker()</code>最后添加成功后会启动Worker线程，而在worker线程中run方法又会调用一个<code>runWorker()</code>方法，这里就是具体执行任务的地方</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">final</span> <span class="keyword">void</span> <span class="title">runWorker</span><span class="params">(Worker w)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//当前执行线程</span></span><br><span class="line">    Thread wt = Thread.currentThread();</span><br><span class="line">    <span class="comment">//拿到任务</span></span><br><span class="line">    Runnable task = w.firstTask; </span><br><span class="line">    w.firstTask = <span class="keyword">null</span>;</span><br><span class="line">    <span class="comment">//前面构造worker的时候设置了state=-1</span></span><br><span class="line">    <span class="comment">//设置state为0，tryRelease(1)</span></span><br><span class="line">    <span class="comment">//其实这样是为了在这之前不会被打断（还没有开始执行任务）</span></span><br><span class="line">    w.unlock(); <span class="comment">// allow interrupts</span></span><br><span class="line">    <span class="keyword">boolean</span> completedAbruptly = <span class="keyword">true</span>; <span class="comment">//是否因为异常而退出？</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">//task为空就从阻塞队列中拿任务</span></span><br><span class="line">        <span class="keyword">while</span> (task != <span class="keyword">null</span> || (task = getTask()) != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">//加锁，但是这个锁不会和其他的Worker互斥，这个锁只是用来判断worker是否在工作</span></span><br><span class="line">            w.lock();</span><br><span class="line">            <span class="comment">// If pool is stopping, ensure thread is interrupted;</span></span><br><span class="line">            <span class="comment">// if not, ensure thread is not interrupted.  This</span></span><br><span class="line">            <span class="comment">// requires a recheck in second case to deal with</span></span><br><span class="line">            <span class="comment">// shutdownNow race while clearing interrupt</span></span><br><span class="line">            <span class="keyword">if</span> ((runStateAtLeast(ctl.get(), STOP) ||</span><br><span class="line">                 (Thread.interrupted() &amp;&amp;</span><br><span class="line">                  runStateAtLeast(ctl.get(), STOP))) &amp;&amp;</span><br><span class="line">                !wt.isInterrupted())</span><br><span class="line">                <span class="comment">//打断当前执行线程wt</span></span><br><span class="line">                wt.interrupt();</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">//空方法交给子类去实现</span></span><br><span class="line">                beforeExecute(wt, task);</span><br><span class="line">                Throwable thrown = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    task.run(); <span class="comment">//执行任务</span></span><br><span class="line">                &#125; <span class="keyword">catch</span> (RuntimeException x) &#123;</span><br><span class="line">                    thrown = x; <span class="keyword">throw</span> x;</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Error x) &#123;</span><br><span class="line">                    thrown = x; <span class="keyword">throw</span> x;</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Throwable x) &#123;</span><br><span class="line">                    thrown = x; <span class="keyword">throw</span> <span class="keyword">new</span> Error(x);</span><br><span class="line">                &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                    <span class="comment">//空方法交给子类去实现</span></span><br><span class="line">                    afterExecute(task, thrown);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                task = <span class="keyword">null</span>;</span><br><span class="line">                w.completedTasks++; <span class="comment">//完成任务数++</span></span><br><span class="line">                w.unlock();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        completedAbruptly = <span class="keyword">false</span>; <span class="comment">//下面的收尾工作会根据这个判断是否调整线程数</span></span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        processWorkerExit(w, completedAbruptly); <span class="comment">//收尾工作</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>🔸 首先获取了参数传递进来的worker携带的任务</p>
<p>🔸 然后执行了w.unlock()，实际上这里就对应了上面Worker类构造器中的setState(-1)，正因为前面设置了state为 -1 所以在unlock()之前，获得锁的CAS操作肯定都会失败，当然这也是为了在任务启动前不会被打断，所以在这里unlock()就又将state设置为了0 也就表示可以通过CAS获得锁了，也可以被shutdown打断了。</p>
<p>🔸 然后这个线程就会执行worker中的任务，如果worker中任务为空就会从阻塞队列中获取任务</p>
<p>🔸 获取到任务后进入循环先进行 lock() 操作，这就代表已经开始执行任务了，这个时候shutdown就无法发送中断信号中断这个线程执行 (注意这个lock并不会和其他的worker互斥，因为每个Worker都是新new出来的，完全不相关的，他们的state状态都是独立的)</p>
<p>🔸 <code>runStateAtLeast(ctl.get(), STOP)</code> 返回<code>ctl.get() &gt;= STOP</code>  ，判断线程池是否正在关闭如果是就打断该线程，如果不是需要确保线程不是Interrupt状态</p>
<p><code>If pool is stopping, ensure thread is interrupted;  if not, ensure thread is not interrupted.</code></p>
<p>🔸<code>beforeExecute()</code> 和<code>afterExecute()</code> 都是空方法交给子类去实现的。</p>
<p>🔸 到finally块里面就代表这个工作线程已经快要结束了，<code>processWorkerExit()</code>  就是处理一些”后事”的</p>
<h3 id="getTask"><a href="#getTask" class="headerlink" title="getTask()"></a>getTask()</h3><p>这个方法就是用来从阻塞队列中获取任务的，如果 <code>getTask()</code> 返回null，在<code>runWorker()</code> 里面接收到<code>null</code> 后就会<strong>跳出循环</strong>进而执行<code>finally</code> 块里面的<code>processWorkerExit()</code> 。而这也就意味着这个线程<code>执行结束</code>了，不会在执行任务了，剩下的就是等待JVM回收这个线程。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> Runnable <span class="title">getTask</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">//是否超时？和keepAliveTime相关</span></span><br><span class="line">    <span class="keyword">boolean</span> timedOut = <span class="keyword">false</span>; <span class="comment">// Did the last poll() time out?</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">        <span class="keyword">int</span> c = ctl.get();</span><br><span class="line">        <span class="keyword">int</span> rs = runStateOf(c);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Check if queue empty only if necessary.</span></span><br><span class="line">        <span class="comment">// 如果线程池状态为SHUTDOWN并且任务队列没任务 或者 线程状态&gt;=STOP</span></span><br><span class="line">        <span class="keyword">if</span> (rs &gt;= SHUTDOWN &amp;&amp; (rs &gt;= STOP || workQueue.isEmpty())) &#123;</span><br><span class="line">            decrementWorkerCount();</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> wc = workerCountOf(c);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// Are workers subject to culling?</span></span><br><span class="line">        <span class="comment">// 是否允许线程超时 允许核心线程超时(主动超时)？ 或者wc大于了核心线程数(被动超时)</span></span><br><span class="line">        <span class="keyword">boolean</span> timed = allowCoreThreadTimeOut || wc &gt; corePoolSize;</span><br><span class="line">		<span class="comment">//此时需要回收多余的线程</span></span><br><span class="line">        <span class="keyword">if</span> ((wc &gt; maximumPoolSize || (timed &amp;&amp; timedOut))</span><br><span class="line">            &amp;&amp; (wc &gt; <span class="number">1</span> || workQueue.isEmpty())) &#123;</span><br><span class="line">            <span class="keyword">if</span> (compareAndDecrementWorkerCount(c)) <span class="comment">//cas减少线程数</span></span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>; <span class="comment">//返回null</span></span><br><span class="line">            <span class="keyword">continue</span>; <span class="comment">//cas失败 继续循环</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//根据timed判断是限时获取还是直接获取</span></span><br><span class="line">            Runnable r = timed ?</span><br><span class="line">                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :</span><br><span class="line">                workQueue.take(); <span class="comment">//阻塞的获取</span></span><br><span class="line">            <span class="keyword">if</span> (r != <span class="keyword">null</span>)</span><br><span class="line">                <span class="keyword">return</span> r;</span><br><span class="line">            <span class="comment">//没获取到，超时了</span></span><br><span class="line">            timedOut = <span class="keyword">true</span>;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException retry) &#123;</span><br><span class="line">            timedOut = <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>🔸 获取线程池状态，如果线程池状态为SHUTDOWN并且任务队列没任务 或者 线程状态&gt;=STOP 就通过CAS自旋减少线程数，然后返回null</p>
<p>🔸 判断是否允许当前线程获取任务超时，如果允许核心线程超时就代表所有线程都会超时限制，又或者是当前线程数超过了核心线程数，也就是经过了扩容，所以核心线程之外的线程都是有超时限制的。</p>
<p>🔸 如果 ① wc超过最大线程数  ②没超过最大线程数，但是超时了并且此时wc&gt;1(留一个处理任务)③没超过最大线程数，但是超时了并且阻塞队列为空，此时需要回收多余的线程</p>
<p>🔸 根据timed选取从阻塞队列中获取任务的方式，要么是限时获取的poll或者一直阻塞的take，获取到了之后返回</p>
<h3 id="processWorkerExit"><a href="#processWorkerExit" class="headerlink" title="processWorkerExit()"></a>processWorkerExit()</h3><p>看名字就知道是一个收尾的方法，执行线程结束后的一些必要收尾工作。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">processWorkerExit</span><span class="params">(Worker w, <span class="keyword">boolean</span> completedAbruptly)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (completedAbruptly) <span class="comment">// If abrupt, then workerCount wasn&#x27;t adjusted</span></span><br><span class="line">        <span class="comment">//如果是因为异常而退出则 getTask() 没有机会去调整线程数所以需要在这里调整</span></span><br><span class="line">        decrementWorkerCount();  <span class="comment">// wc--</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">    mainLock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">//完成任务总数+=该worker完成的任务数</span></span><br><span class="line">        completedTaskCount += w.completedTasks;</span><br><span class="line">        <span class="comment">//移除出线程集workers</span></span><br><span class="line">        workers.remove(w);</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        mainLock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//尝试结束线程池</span></span><br><span class="line">    tryTerminate();</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//获取ctl</span></span><br><span class="line">    <span class="keyword">int</span> c = ctl.get();</span><br><span class="line">    <span class="keyword">if</span> (runStateLessThan(c, STOP)) &#123;</span><br><span class="line">        <span class="comment">//非异常结束</span></span><br><span class="line">        <span class="keyword">if</span> (!completedAbruptly) &#123;</span><br><span class="line">            <span class="comment">//最小值根据是否允许核心线程超时来判断</span></span><br><span class="line">            <span class="keyword">int</span> min = allowCoreThreadTimeOut ? <span class="number">0</span> : corePoolSize;</span><br><span class="line">            <span class="keyword">if</span> (min == <span class="number">0</span> &amp;&amp; ! workQueue.isEmpty())</span><br><span class="line">                min = <span class="number">1</span>; <span class="comment">//如果最小为0并且任务队列不为空则保证线程池中至少有一个线程执行这些任务</span></span><br><span class="line">            <span class="keyword">if</span> (workerCountOf(c) &gt;= min)</span><br><span class="line">                <span class="keyword">return</span>; <span class="comment">// replacement not needed</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//1.异常结束，新增加一个线程到线程池,相当于替换了异常的线程</span></span><br><span class="line">        <span class="comment">//2.非异常结束，工作线程小于核心线程，增加线程，确保在不允许核心线程超时的情况下线程数不小于corePoolSize</span></span><br><span class="line">        addWorker(<span class="keyword">null</span>, <span class="keyword">false</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>runStateLessThan</code>  c &lt; STOP 返回true就说明是<code>SHUTDOWN</code> 或者<code>RUNNING</code> ，到这里该工作线程（Worker）的生命周期就结束了。</p>
<h3 id="工作线程的生命周期"><a href="#工作线程的生命周期" class="headerlink" title="工作线程的生命周期"></a>工作线程的生命周期</h3><p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top/blog/20190803/NbjiMxDqJlu4.png?imageslim"
                      alt="mark"
                ></p>
<h3 id="tryTerminate"><a href="#tryTerminate" class="headerlink" title="tryTerminate()"></a>tryTerminate()</h3><p>在上面的处理收尾工作的<code>processWorkerExit()</code> 的时候中间调用了一个 <code>tryTerminate()</code> 方法</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">final</span> <span class="keyword">void</span> <span class="title">tryTerminate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">        <span class="keyword">int</span> c = ctl.get();</span><br><span class="line">        <span class="comment">//如果是在RUNNING状态 直接return</span></span><br><span class="line">        <span class="comment">//如果已经是TIDYING或者TERMINATED状态 直接return</span></span><br><span class="line">        <span class="comment">//如果是SHUTDOWN状态并且阻塞队列中还有任务 直接return</span></span><br><span class="line">        <span class="comment">//return就说明线程池还不到关闭的时候</span></span><br><span class="line">        <span class="keyword">if</span> (isRunning(c) ||</span><br><span class="line">            runStateAtLeast(c, TIDYING) ||</span><br><span class="line">            (runStateOf(c) == SHUTDOWN &amp;&amp; ! workQueue.isEmpty()))</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        <span class="comment">//到这里就说明要么是STOP状态，要么是SHUTDOWN状态阻塞队列也没任务了</span></span><br><span class="line">        <span class="keyword">if</span> (workerCountOf(c) != <span class="number">0</span>) &#123; <span class="comment">// Eligible to terminate</span></span><br><span class="line">            <span class="comment">//中断一个空闲的worker线程</span></span><br><span class="line">            interruptIdleWorkers(ONLY_ONE);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">		</span><br><span class="line">        <span class="comment">//wc==0 没有线程存活了</span></span><br><span class="line">        <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">        mainLock.lock();</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//CAS自旋 修改线程池状态为TIDYING</span></span><br><span class="line">            <span class="keyword">if</span> (ctl.compareAndSet(c, ctlOf(TIDYING, <span class="number">0</span>))) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    terminated(); <span class="comment">//空方法,交给子类去实现的</span></span><br><span class="line">                &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                    <span class="comment">//设置状态为 TERMINATED</span></span><br><span class="line">                    ctl.set(ctlOf(TERMINATED, <span class="number">0</span>));</span><br><span class="line">                    <span class="comment">//唤醒termination上awiat的线程</span></span><br><span class="line">                    termination.signalAll();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            mainLock.unlock();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// else retry on failed CAS</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里最后的<code>termination.signalAll()</code> 实际上是唤醒的<code>awaitTermination()</code> 方法阻塞的线程</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">awaitTermination</span><span class="params">(<span class="keyword">long</span> timeout, TimeUnit unit)</span></span></span><br><span class="line"><span class="function">    <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">    <span class="keyword">long</span> nanos = unit.toNanos(timeout);</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">    mainLock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">            <span class="keyword">if</span> (runStateAtLeast(ctl.get(), TERMINATED))</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">            <span class="keyword">if</span> (nanos &lt;= <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">            <span class="comment">//限时等待</span></span><br><span class="line">            nanos = termination.awaitNanos(nanos);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        mainLock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="shutdown"><a href="#shutdown" class="headerlink" title="shutdown()"></a>shutdown()</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">    mainLock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        checkShutdownAccess();</span><br><span class="line">        <span class="comment">//CAS自旋设置线程池状态为 SHUTDOWN</span></span><br><span class="line">        advanceRunState(SHUTDOWN);</span><br><span class="line">        <span class="comment">//打断idle(空闲)的worker</span></span><br><span class="line">        interruptIdleWorkers(); </span><br><span class="line">        onShutdown(); <span class="comment">// hook for ScheduledThreadPoolExecutor</span></span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        mainLock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">    tryTerminate();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里关键的就是这个打断空闲线程的操作。</p>
<h3 id="interruptIdleWorkers"><a href="#interruptIdleWorkers" class="headerlink" title="interruptIdleWorkers()"></a>interruptIdleWorkers()</h3><p>打断空闲的worker，这里的空闲线程其实指的就是在阻塞队列上获取不到任务而阻塞的线程</p>
<p>经过上面的分析我们知道Worker会不断的从阻塞队列中去拿任务也就是 <code>getTask()</code> 方法，如果阻塞队列为空就会阻塞住 直到有任务提交到阻塞队列中，或者执行线程被中断。</p>
<p>这里我们是要SHUTDOWN那阻塞队列中肯定是不会再有任务提交，所以<code>take()</code> 会阻塞住，所以我们就只能通过打断执行线程的方式来打断<code>take()</code> 操作，否则会一直阻塞，线程池无法关闭。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">interruptIdleWorkers</span><span class="params">(<span class="keyword">boolean</span> onlyOne)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">    mainLock.lock(); <span class="comment">//加锁，因为Wokers是HashSet是线程不安全的</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (Worker w : workers) &#123;</span><br><span class="line">            Thread t = w.thread;</span><br><span class="line">            <span class="comment">//没有被打断并且没有在工作(空闲)</span></span><br><span class="line">            <span class="keyword">if</span> (!t.isInterrupted() &amp;&amp; w.tryLock()) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    <span class="comment">//打断Worker里面的线程</span></span><br><span class="line">                    t.interrupt();</span><br><span class="line">                &#125; <span class="keyword">catch</span> (SecurityException ignore) &#123;</span><br><span class="line">                &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                    w.unlock();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//只打断一个就直接break</span></span><br><span class="line">            <span class="keyword">if</span> (onlyOne)</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        mainLock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>🔸首先获取了mainLock保证了workers的线程安全避免产生并发修改异常。</p>
<p>🔸然后遍历workers，打断那些没有被打断并且没有工作的线程，那这里怎么知道线程是不是在工作呢？</p>
<p>别忘了前面提到的Worker类借助AQS实现了一个<code>不可重入</code>的<code>lock</code> 方法，而在worker执行任务的时候会执行 <code>lock</code> 加锁，所以在这里<code>tryLock()</code> 如果返回<code>true</code>则说明 并没有在工作可以打断，反之如果正在工作<code>tryLock()</code> 不可重入，无法获取到自己持有的锁返回false，所以线程肯定是在工作状态所以不应该打断，这些线程会在执行完任务后自行了断，因为线程池状态已经设置为<code>SHUTDOWN</code> 当然前提是这些任务是<strong>可终止的</strong></p>
<p>🔸打断后释放<code>tryLock()</code>获取到的锁</p>
<p>🔸如果只打断一个就直接break，否则就继续下一轮循环</p>
<p>🔸释放mianLock</p>
<blockquote>
<p>瞎猜: 这里可以通过getState判断线程状态但是有可能在执行任务的过中阻塞</p>
</blockquote>
<h3 id="shutdownNow"><a href="#shutdownNow" class="headerlink" title="shutdownNow()"></a>shutdownNow()</h3><p>和上面的shutdown()一样都是用来关闭线程池的但是看方法名就知道这个比较粗暴，shutdownNow立刻马上关闭，一点情面都不给😂，虽然说是打断所有的线程但是毕竟使用的是<code>Interrupt</code> ，也许别人正在执行的线程根本就不会理你😂，所以在提交任务的时候要对任务进行正确的interrupt响应，或者确保线程不会一直阻塞否则线程池就无法正常关闭</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> List&lt;Runnable&gt; <span class="title">shutdownNow</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    List&lt;Runnable&gt; tasks;</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">    mainLock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        checkShutdownAccess();</span><br><span class="line">        <span class="comment">//CAS自旋设置状态为STOP</span></span><br><span class="line">        advanceRunState(STOP);</span><br><span class="line">        <span class="comment">//打断所有的线程包括正在工作的线程</span></span><br><span class="line">        interruptWorkers();</span><br><span class="line">        <span class="comment">//排干阻塞队列，因为已经STOP了不会再执行队列里面的任务了</span></span><br><span class="line">        tasks = drainQueue();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        mainLock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//尝试关闭线程池</span></span><br><span class="line">    tryTerminate();</span><br><span class="line">    <span class="keyword">return</span> tasks;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="interruptWorkers"><a href="#interruptWorkers" class="headerlink" title="interruptWorkers()"></a>interruptWorkers()</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">interruptWorkers</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">this</span>.mainLock;</span><br><span class="line">    mainLock.lock();</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (Worker w : workers)</span><br><span class="line">            <span class="comment">//打断所有启动的线程</span></span><br><span class="line">            w.interruptIfStarted();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        mainLock.unlock();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>打断了所有的启动的线程，即使他们可能不会响应这个Interrupted信号，但是由于线程池状态已经变为了STOP，所以他们也活不长了(当然前提是执行的任务是可以结束的)，在下一次获取任务的时候就会直接return 。</p>
<h2 id="细节是魔鬼"><a href="#细节是魔鬼" class="headerlink" title="细节是魔鬼"></a>细节是魔鬼</h2><p>在群里面看见的问题，为什么线程池要用 线程不安全的 <code>HashSet</code> 然后设置了一个 <code>mainLock</code> 控制并发，而不是直接使用线程安全的并发集合？</p>
<p>这一点其实在源码的注释中已经说的很清楚了，之前一直没有注意到</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Lock held on access to workers set and related bookkeeping.</span></span><br><span class="line"><span class="comment"> * While we could use a concurrent set of some sort, it turns out</span></span><br><span class="line"><span class="comment"> * to be generally preferable to use a lock. Among the reasons is</span></span><br><span class="line"><span class="comment"> * that this serializes interruptIdleWorkers, which avoids</span></span><br><span class="line"><span class="comment"> * unnecessary interrupt storms, especially during shutdown.</span></span><br><span class="line"><span class="comment"> * Otherwise exiting threads would concurrently interrupt those</span></span><br><span class="line"><span class="comment"> * that have not yet interrupted. It also simplifies some of the</span></span><br><span class="line"><span class="comment"> * associated statistics bookkeeping of largestPoolSize etc. We</span></span><br><span class="line"><span class="comment"> * also hold mainLock on shutdown and shutdownNow, for the sake of</span></span><br><span class="line"><span class="comment"> * ensuring workers set is stable while separately checking</span></span><br><span class="line"><span class="comment"> * permission to interrupt and actually interrupting.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">final</span> ReentrantLock mainLock = <span class="keyword">new</span> ReentrantLock();</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>一开始还挺抗拒的，感觉有的地方有的看不懂（英语渣渣留下眼泪）然后去stackoverflower上看了一下找到了一个答案  <a class="link"   target="_blank" rel="noopener" href="https://stackoverflow.com/questions/31942117/using-reentrantlock-in-threadpoolexecutor-to-ensure-thread-safe-workers" >Using ReentrantLock in ThreadPoolExecutor to ensure thread-safe workers<i class="fas fa-external-link-alt"></i></a> </p>
<p>大概总结一下就是两点</p>
<ol>
<li><p>避免 “中断风暴” ，如果是用的显式锁那么如果有10个线程同时去执行shutdown方法，那么10个线程会排队去执行<code>interruptIdleWorkers</code> ，如果使用并发安全的队列的话，在10个线程同时去执行shutdown方法，那么肯定会同时去 <code>interruptIdleWorkers</code> 也就是所谓的中断风暴</p>
<blockquote>
<p><a class="link"   target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Interrupt_storm" >中断风暴(维基百科)<i class="fas fa-external-link-alt"></i></a> 中文几乎搜不到相关资料，其实就是字面意思，而太多的中断请求会的影响系统的整体性能，不得不说大师就是大师，细节之处则更能体现水平，我等也只能膜拜了</p>
</blockquote>
</li>
<li><p>另一点就是为了方便统计线程池的一些信息比如 <code>largestPoolSize</code> 等，这点也好理解，使用并发的Set只能保这个set的并发安全，而对于其他的一些线程池的相关的信息统计起来就比较麻烦，可能又需要另外的加锁，所以索性就直接搞一个全局的锁，一举两得</p>
</li>
</ol>
<h2 id="ThreadPoolExecutor使用"><a href="#ThreadPoolExecutor使用" class="headerlink" title="ThreadPoolExecutor使用"></a>ThreadPoolExecutor使用</h2><h3 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">ThreadPoolExecutor</span><span class="params">(<span class="keyword">int</span> corePoolSize,</span></span></span><br><span class="line"><span class="params"><span class="function">                          <span class="keyword">int</span> maximumPoolSize,</span></span></span><br><span class="line"><span class="params"><span class="function">                          <span class="keyword">long</span> keepAliveTime,</span></span></span><br><span class="line"><span class="params"><span class="function">                          TimeUnit unit,</span></span></span><br><span class="line"><span class="params"><span class="function">                          BlockingQueue&lt;Runnable&gt; workQueue,</span></span></span><br><span class="line"><span class="params"><span class="function">                          ThreadFactory threadFactory,</span></span></span><br><span class="line"><span class="params"><span class="function">                          RejectedExecutionHandler handler)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (corePoolSize &lt; <span class="number">0</span> ||</span><br><span class="line">        maximumPoolSize &lt;= <span class="number">0</span> ||</span><br><span class="line">        maximumPoolSize &lt; corePoolSize ||</span><br><span class="line">        keepAliveTime &lt; <span class="number">0</span>)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException();</span><br><span class="line">    <span class="keyword">if</span> (workQueue == <span class="keyword">null</span> || threadFactory == <span class="keyword">null</span> || handler == <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">    <span class="keyword">this</span>.acc = System.getSecurityManager() == <span class="keyword">null</span> ?</span><br><span class="line">            <span class="keyword">null</span> :</span><br><span class="line">            AccessController.getContext();</span><br><span class="line">    <span class="keyword">this</span>.corePoolSize = corePoolSize;</span><br><span class="line">    <span class="keyword">this</span>.maximumPoolSize = maximumPoolSize;</span><br><span class="line">    <span class="keyword">this</span>.workQueue = workQueue;</span><br><span class="line">    <span class="keyword">this</span>.keepAliveTime = unit.toNanos(keepAliveTime);</span><br><span class="line">    <span class="keyword">this</span>.threadFactory = threadFactory;</span><br><span class="line">    <span class="keyword">this</span>.handler = handler;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>其实从中也可以看出对各个参数的一些限制。</p>
<p><strong>corePoolSize：</strong>核心池的大小，这个参数与后面讲述的线程池的实现原理有非常大的关系。在创建了线程池后，默认情况下，线程池中并没有任何线程，而是等待有任务到来才创建线程去执行任务，除非调用了<code>prestartAllCoreThreads()</code>或者<code>prestartCoreThread()</code>方法，从这2个方法的名字就可以看出，是预创建线程的意思，即在没有任务到来之前就创建corePoolSize个线程或者一个线程。<code>默认情况下</code>，在创建了线程池后，线程池中的线程数为0，当有任务来之后，就会创建一个线程去执行任务，当线程池中的线程数目达到corePoolSize后，就会把到达的任务放到缓存队列当中</p>
<p><strong>maximumPoolSize：</strong>线程池最大线程数，它表示在线程池中最多允许创建多少个线程</p>
<p><strong>keepAliveTime</strong>：表示线程没有任务执行时最多保持多久时间会终止。默认情况下，只有当<code>线程池中的线程数大于corePoolSize时</code>，keepAliveTime才会起作用，直到线程池中的线程数不大于corePoolSize：即当线程池中的线程数大于<code>corePoolSize</code>时，如果一个线程空闲的时间达到keepAliveTime，则会终止，直到线程池中的线程数不超过corePoolSize，但是如果调用了<code>allowCoreThreadTimeOut(boolean)</code>方法，在线程池中的线程数不大于corePoolSize时，keepAliveTime参数也会起作用，直到线程池中的线程数为0，这些内容其实在上面的深入源码中都有过分析。</p>
<p><strong>unit：</strong>参数keepAliveTime的时间单位</p>
<p><strong>workQueue</strong>：一个阻塞队列，用来存储等待执行的任务，这个参数的选择会对线程池的运行过程产生重大影响</p>
<p><strong>threadFactory</strong>：线程工厂，主要用来创建线程(根据传进来的Runnable/Callable)</p>
<p><strong>handler</strong>：表示当拒绝处理任务时的策略，有以下四种取值</p>
<ul>
<li><strong>ThreadPoolExecutor.AbortPolicy</strong> 丢弃任务并抛出RejectedExecutionException异常。 </li>
<li><strong>ThreadPoolExecutor.DiscardPolicy</strong> 也是丢弃任务，但是不抛出异常。 </li>
<li><strong>ThreadPoolExecutor.DiscardOldestPolicy</strong> 丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）</li>
<li><strong>ThreadPoolExecutor.CallerRunsPolicy</strong>  由调用线程处理该任务 </li>
</ul>
<h3 id="线程池的关闭"><a href="#线程池的关闭" class="headerlink" title="线程池的关闭"></a>线程池的关闭</h3><p><code>shutdown()</code>  <code>shutdownNow()</code> ，上面已经分析过了，就不再过多介绍了。</p>
<h3 id="工厂方法"><a href="#工厂方法" class="headerlink" title="工厂方法"></a>工厂方法</h3><p>上面的构造器中一共有7个参数，可见要构造一个线程池并非那么容易，所以jdk 在<code>Executors</code> 类中为我们提供了一些工厂方法，可以直接构造一些特定的线程池。</p>
<p><strong>newCachedThreadPool()</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> ExecutorService <span class="title">newCachedThreadPool</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> ThreadPoolExecutor(<span class="number">0</span>, Integer.MAX_VALUE,</span><br><span class="line">                                  <span class="number">60L</span>, TimeUnit.SECONDS,</span><br><span class="line">                                  <span class="keyword">new</span> SynchronousQueue&lt;Runnable&gt;());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可以看到<code>core</code>为0，最大值为<code>Integer.MAX_VALUE</code>，任务队列使用的<code>SynchronousQueue</code> ，这个队列是一个很奇葩的阻塞队列，实际上它不是一个真正的队列，每个删除操作都要等待插入操作，反之每个插入操作也都要等待删除动作，只有两个都准备好的时候才不会阻塞，所以它内部不会为队列元素维护空间，也就是说并不会缓存任务，一旦提交了(put)任务，要么就由空闲线程去执行(take)，要么创建一条新线程去执行(take)。</p>
<p><strong>newFixedThreadPool()</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> ExecutorService <span class="title">newFixedThreadPool</span><span class="params">(<span class="keyword">int</span> nThreads)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> ThreadPoolExecutor(nThreads, nThreads,</span><br><span class="line">                                  <span class="number">0L</span>, TimeUnit.MILLISECONDS,</span><br><span class="line">                                  <span class="keyword">new</span> LinkedBlockingQueue&lt;Runnable&gt;());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可以看到，最大值和core都是 <code>nThread</code> ，也就是最多<code>nThread</code>个线程，阻塞队列采用 <code>LinkedBlockQueue</code> </p>
<p><strong>newSingleThreadExecutor()</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> ExecutorService <span class="title">newSingleThreadExecutor</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> FinalizableDelegatedExecutorService</span><br><span class="line">        (<span class="keyword">new</span> ThreadPoolExecutor(<span class="number">1</span>, <span class="number">1</span>,</span><br><span class="line">                                <span class="number">0L</span>, TimeUnit.MILLISECONDS,</span><br><span class="line">                                <span class="keyword">new</span> LinkedBlockingQueue&lt;Runnable&gt;()));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>等价于<code>newFixedThreadPool(1)</code> ，但是这里的返回值经过了一层包装 返回的不再是<code>ThreadPoolExecutor</code> 也就是不会再有那些扩展的monitor方法</p>
<blockquote>
<p>A wrapper class that exposes only the ExecutorService methods  of an ExecutorService implementation.</p>
</blockquote>
<p>类似的方法其实还有一些，像<code>newWorkStealingPool</code> 等，感兴趣可以自己去查一查。</p>
<p>其实这里阿里巴巴Java开发规范并不建议使用工厂方法创建线程</p>
<p><img  
                     lazyload
                     src="/images/loading.svg"
                     data-src="http://static.imlgw.top/blog/20190806/lMVPdlPqEPNO.png?imageslim"
                      alt="mark"
                ></p>
<p>所以建议还是通过构造器的方式去创建线程，这样也更加灵活更加可控。</p>

        </div>

        
            <div class="post-copyright-info">
                <div class="article-copyright-info-container">
    <ul>
        <li>本文标题：ThreadPoolExecutor源码解析</li>
        <li>本文作者：Resolmi</li>
        <li>创建时间：2019-07-30 00:00:00</li>
        <li>
            本文链接：https://imlgw.top/2019/07/30/ca94e89b/
        </li>
        <li>
            版权声明：本博客所有文章除特别声明外，均采用 <a class="license" target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">BY-NC-SA</a> 许可协议。转载请注明出处！
        </li>
    </ul>
</div>

            </div>
        

        
            <div class="article-nav">
                
                    <div class="article-prev">
                        <a class="prev"
                           rel="prev"
                           href="/2019/08/07/159c6098/"
                        >
                            <span class="left arrow-icon flex-center">
                              <i class="fas fa-chevron-left"></i>
                            </span>
                            <span class="title flex-center">
                                <span class="post-nav-title-item">阻塞队列</span>
                                <span class="post-nav-item">上一篇</span>
                            </span>
                        </a>
                    </div>
                
                
                    <div class="article-next">
                        <a class="next"
                           rel="next"
                           href="/2019/07/24/7187a079/"
                        >
                            <span class="title flex-center">
                                <span class="post-nav-title-item">JUC并发工具包</span>
                                <span class="post-nav-item">下一篇</span>
                            </span>
                            <span class="right arrow-icon flex-center">
                              <i class="fas fa-chevron-right"></i>
                            </span>
                        </a>
                    </div>
                
            </div>
        

        
            <div class="comment-container">
                <div class="comments-container">
    <div id="comment-anchor"></div>
    <div class="comment-area-title">
        <i class="fas fa-comments">&nbsp;评论</i>
    </div>
    

        
            <section class="disqus-comments">
<div id="disqus_thread">
  <noscript>Please enable JavaScript to view the <a target="_blank" rel="noopener" href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>
</section>

<script>
var disqus_shortname = 'imlgw';

var disqus_url = 'https://imlgw.top/2019/07/30/ca94e89b/';

(function(){
  var dsq = document.createElement('script');
  dsq.type = 'text/javascript';
  dsq.async = true;
  dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>

<script id="dsq-count-scr" src="//imlgw.disqus.com/count.js" async></script>
        
    
</div>

            </div>
        
    </div>
</div>


                
            </div>

        </div>

        <div class="page-main-content-bottom">
            <footer class="footer">
    <div class="info-container">
        <div class="copyright-info info-item">
            &copy;
            
              <span>2018</span>&nbsp;-&nbsp;
            
            2021&nbsp;<i class="fas fa-heart icon-animate"></i>&nbsp;<a href="/">Resolmi</a>
        </div>
        
            <script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
            <div class="website-count info-item">
                
                    <span id="busuanzi_container_site_uv">
                        访问人数&nbsp;<span id="busuanzi_value_site_uv"></span>&ensp;
                    </span>
                
                
                    <span id="busuanzi_container_site_pv">
                        总访问量&nbsp;<span id="busuanzi_value_site_pv"></span>
                    </span>
                
            </div>
        
        
            <div class="icp-info info-item"><a target="_blank" rel="nofollow" href="https://beian.miit.gov.cn">鄂ICP备18011208号</a></div>
        
    </div>
</footer>

        </div>
    </div>

    
        <div class="post-tools">
            <div class="post-tools-container">
    <ul class="tools-list">
        <!-- TOC aside toggle -->
        
            <li class="tools-item page-aside-toggle">
                <i class="fas fa-outdent"></i>
            </li>
        

        <!-- go comment -->
        
            <li class="go-comment">
                <i class="fas fa-comment"></i>
            </li>
        
    </ul>
</div>

        </div>
    

    <div class="right-bottom-side-tools">
        <div class="side-tools-container">
    <ul class="side-tools-list">
        <li class="tools-item tool-font-adjust-plus flex-center">
            <i class="fas fa-search-plus"></i>
        </li>

        <li class="tools-item tool-font-adjust-minus flex-center">
            <i class="fas fa-search-minus"></i>
        </li>

        <li class="tools-item tool-expand-width flex-center">
            <i class="fas fa-arrows-alt-h"></i>
        </li>

        <li class="tools-item tool-dark-light-toggle flex-center">
            <i class="fas fa-moon"></i>
        </li>

        <!-- rss -->
        

        

        <li class="tools-item tool-scroll-to-bottom flex-center">
            <i class="fas fa-arrow-down"></i>
        </li>
    </ul>

    <ul class="exposed-tools-list">
        <li class="tools-item tool-toggle-show flex-center">
            <i class="fas fa-cog fa-spin"></i>
        </li>
        
            <li class="tools-item tool-scroll-to-top flex-center">
                <i class="arrow-up fas fa-arrow-up"></i>
                <span class="percent"></span>
            </li>
        
    </ul>
</div>

    </div>

    
        <aside class="page-aside">
            <div class="post-toc-wrap">
    <div class="post-toc">
        <ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B7%B1%E5%85%A5ThreadPoolExecutor%E6%BA%90%E7%A0%81"><span class="nav-number">1.</span> <span class="nav-text">深入ThreadPoolExecutor源码</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%B1%BB%E7%BB%93%E6%9E%84"><span class="nav-number">1.1.</span> <span class="nav-text">类结构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%8A%B6%E6%80%81"><span class="nav-number">1.2.</span> <span class="nav-text">线程池状态</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2%E8%BF%87%E7%A8%8B"><span class="nav-number">1.2.1.</span> <span class="nav-text">状态转换过程</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F"><span class="nav-number">1.3.</span> <span class="nav-text">成员变量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#execute"><span class="nav-number">1.4.</span> <span class="nav-text">execute()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#addWorker"><span class="nav-number">1.5.</span> <span class="nav-text">addWorker()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#addWorkerFailed"><span class="nav-number">1.6.</span> <span class="nav-text">addWorkerFailed()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Worker%E7%B1%BB"><span class="nav-number">1.7.</span> <span class="nav-text">Worker类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#runWorker"><span class="nav-number">1.8.</span> <span class="nav-text">runWorker()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#getTask"><span class="nav-number">1.9.</span> <span class="nav-text">getTask()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#processWorkerExit"><span class="nav-number">1.10.</span> <span class="nav-text">processWorkerExit()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B7%A5%E4%BD%9C%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">1.11.</span> <span class="nav-text">工作线程的生命周期</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tryTerminate"><span class="nav-number">1.12.</span> <span class="nav-text">tryTerminate()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#shutdown"><span class="nav-number">1.13.</span> <span class="nav-text">shutdown()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#interruptIdleWorkers"><span class="nav-number">1.14.</span> <span class="nav-text">interruptIdleWorkers()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#shutdownNow"><span class="nav-number">1.15.</span> <span class="nav-text">shutdownNow()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#interruptWorkers"><span class="nav-number">1.16.</span> <span class="nav-text">interruptWorkers()</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BB%86%E8%8A%82%E6%98%AF%E9%AD%94%E9%AC%BC"><span class="nav-number">2.</span> <span class="nav-text">细节是魔鬼</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#ThreadPoolExecutor%E4%BD%BF%E7%94%A8"><span class="nav-number">3.</span> <span class="nav-text">ThreadPoolExecutor使用</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95"><span class="nav-number">3.1.</span> <span class="nav-text">构造方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E5%85%B3%E9%97%AD"><span class="nav-number">3.2.</span> <span class="nav-text">线程池的关闭</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95"><span class="nav-number">3.3.</span> <span class="nav-text">工厂方法</span></a></li></ol></li></ol>
    </div>
</div>
        </aside>
    

    <div class="image-viewer-container">
    <img src="">
</div>


    
        <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
          <span class="search-input-field-pre">
            <i class="fas fa-keyboard"></i>
          </span>
            <div class="search-input-container">
                <input autocomplete="off"
                       autocorrect="off"
                       autocapitalize="off"
                       placeholder="搜索..."
                       spellcheck="false"
                       type="search"
                       class="search-input"
                >
            </div>
            <span class="popup-btn-close">
                <i class="fas fa-times"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fas fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>

    

</main>



<script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/utils.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/main.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/header-shrink.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/back2top.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/dark-light-toggle.js"></script>


    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/local-search.js"></script>



    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/code-copy.js"></script>



    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/lazyload.js"></script>


<div class="post-scripts pjax">
    
        <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/left-side-toggle.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/libs/anime.min.js"></script><script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/toc.js"></script>
    
</div>


    <script src="//cdn.jsdelivr.net/npm/hexo-theme-keep@3.4.3/source/js/libs/pjax.min.js"></script>
<script>
    window.addEventListener('DOMContentLoaded', () => {
        window.pjax = new Pjax({
            selectors: [
                'head title',
                '.page-container',
                '.pjax'
            ],
            history: true,
            debug: false,
            cacheBust: false,
            timeout: 0,
            analytics: false,
            currentUrlFullReload: false,
            scrollRestoration: false,
            // scrollTo: true,
        });

        document.addEventListener('pjax:send', () => {
            KEEP.utils.pjaxProgressBarStart();
        });

        document.addEventListener('pjax:complete', () => {
            KEEP.utils.pjaxProgressBarEnd();
            window.pjax.executeScripts(document.querySelectorAll('script[data-pjax], .pjax script'));
            KEEP.refresh();
        });
    });
</script>



<script src="https://cdn.jsdelivr.net/npm/live2d-widget@3.x/lib/L2Dwidget.min.js"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"https://cdn.jsdelivr.net/npm/live2d-widget-model-hijiki@1.0.5/assets/hijiki.model.json"},"display":{"superSample":2,"width":160,"height":320,"position":"right","hOffset":0,"vOffset":-70},"mobile":{"show":false,"scale":0.2},"log":false});</script></body>
</html>
